﻿using Mrsoft.Common;
using Mrsoft.Model;
using System;
using System.Threading;
using xiao;


namespace Mrsoft.Core
{

    /// <summary>
    /// CALL通信接口枚举值
    /// </summary>
    enum FuncId
    {
        VmMyTalknpc = 1,
        VmMyOpennpc = 2,
        VmMyWalk = 3,
        VmMyOpenbag = 4,
        VmMyCatchbag = 5,
        VmMySkill = 6,
        VmMyLUa = 7,
        VmMyTest = 8,
        VmMyLevelup = 9,
        VmMyCailiaojiagong = 10,
        VmMyDrop = 11
    }

    /// <summary>
    /// 对应实体调用dll流程
    /// </summary>
    partial class DirectDealGame
    {
        private ICore xiao;

        /// <summary>
        /// 实例绑定的游戏HWND
        /// </summary>
        private int gameHwnd;

        #region ICall调用

        /// <summary>
        /// Core里游戏CALL函数调用
        /// 类封装接口
        /// </summary>
        /// <param name="funcId">函数接口值</param>
        /// <param name="args">调用的参数表会写入游戏内存</param>
        /// <returns></returns>
        private bool DllCall(FuncId funcId, params Int32[] args) {
            //多线程同步
            lock (xiao) {
                return xiao.Call((int)funcId, args);
            }
        }
        #endregion

        #region 本地调用
        protected bool TalkNpc(string diaContent) {
            if (NativeMethods.Ri(dwProcessId, Data.FLAG_NPC, Data.FLAG_OFF_1, Data.FLAG_OFF_2, Data.FLAG_OFF_3) != 1)
                return false;
            int diaNum = NativeMethods.Rb(dwProcessId, Data.CALL_NPCDIA, 0x34, 4);
            for (int k = 0; k < diaNum; k++) {
                Console.WriteLine(NativeMethods.Rs(dwProcessId, Data.CALL_NPCDIA, 0x34, (8 + (k * 0x118)) + 0xe));
                if (NativeMethods.Rs(dwProcessId, Data.CALL_NPCDIA, 0x34, (8 + (k * 0x118)) + 0xe).Contains(diaContent)) {
                    //talk(DWORD diaBase, DWORD diaId, DWORD npcId, DWORD talkCall);
                    DllCall(FuncId.VmMyTalknpc,     //funcId
                        Data.CALL_NPCDIA,           //npc对话框基址
                        NativeMethods.Ri(dwProcessId, Data.CALL_NPCDIA, 0x34, (8 + (k * 0x118)) + 8),       //NPC对话项ID
                        NativeMethods.Ri(dwProcessId, Data.CALL_NPCDIA, 0x34, (8 + (k * 0x118)) + 0x110),   //npcID
                        Data.CALL_TALKNPC   //对话Call地址
                        );
                    return true;
                }
            }
            return false;
        }

        protected bool Catch(int id, bool auto = true) {
            //openBag(DWORD bagId, DWORD autoAddrBase, DWORD autoAddrOff, DWORD JsBase, DWORD JS_OFF_1, DWORD ECX_ESI, DWORD CallAddr);
            return DllCall(FuncId.VmMyOpenbag, id, Data.CALL_CATCH_AUTO, Data.CALL_OFF_CATCH_ALL, Data.JS, Data.JS_OFF_1, Data.CALL_ECX_ESI, Data.CALL_OPEN_BAG);
        }

        protected bool TalkNpc(int npcId = -1, string diaContent = "") {
            int npcState = NativeMethods.Ri(dwProcessId, Data.FLAG_NPC, Data.FLAG_OFF_1, Data.FLAG_OFF_2, Data.FLAG_OFF_3);
            if (npcId != -1) {
                //openNpc(DWORD NpcId, DWORD JsBase, DWORD JS_OFF_1, DWORD ECX_ESI, DWORD CALLAddr);
                if (!DllCall(FuncId.VmMyOpennpc, npcId, Data.JS, Data.JS_OFF_1, Data.CALL_ECX_ESI, Data.CALL_OPENNPC))
                    return false;
                if (npcState == 1)
                    Thread.Sleep(1000);//打开了的就固定执行等待命令
                else {
                    for (int i = 0; i < 30; i++)//最长等待3秒
                    {
                        Thread.Sleep(100);
                        npcState = NativeMethods.Ri(dwProcessId, Data.FLAG_NPC, Data.FLAG_OFF_1, Data.FLAG_OFF_2, Data.FLAG_OFF_3);
                        if (npcState == 1)
                            break;
                    }
                }
            }
            if (string.IsNullOrEmpty(diaContent))
                return true;
            return TalkNpc(diaContent);
        }

        protected bool Catch() {
            //void catchBag(DWORD Call_Off, DWORD CallAddr);
            return DllCall(FuncId.VmMyCatchbag, Data.CALL_OFF_CATCH, Data.PET);
        }

        protected bool Walk(float x, float y) {
            //walk(DWORD X, DWORD Y, DWORD JsBase, DWORD JS_OFF_1, DWORD ECX_ESI, DWORD CallAddr);
            _tarXy.X = x;
            _tarXy.Y = y;
            return DllCall(FuncId.VmMyWalk, x.GetHashCode(), y.GetHashCode(), Data.JS, Data.JS_OFF_1, Data.CALL_ECX_ESI, Data.CALL_WALK);
        }

        protected bool Skill_JS(int skillId, int tarId = -1, float x = 0xBF800000, float y = 0xBF800000) {
            //void skill(DWORD skillId, DWORD TarId, DWORD X, DWORD Y, DWORD JsBase, DWORD JS_OFF_1, DWORD ECX_ESI, DWORD CALLAddr);
            return DllCall(FuncId.VmMySkill, skillId, tarId, x.GetHashCode(), y.GetHashCode(), Data.JS, Data.JS_OFF_1, Data.CALL_ECX_ESI, Data.CALL_SKILL_JS);
        }

        protected bool Skill_Common(int skillId, int tarId = -1, float x = 0xBF800000, float y = 0xBF800000) {
            //void skill(DWORD skillId, DWORD TarId, DWORD X, DWORD Y, DWORD JsBase, DWORD JS_OFF_1, DWORD ECX_ESI, DWORD CALLAddr);
            return DllCall(FuncId.VmMySkill, skillId, tarId, x.GetHashCode(), y.GetHashCode(), Data.JS, Data.JS_OFF_1, Data.CALL_ECX_ESI, Data.CALL_SKILL_COMMON);
        }

        protected bool Walk(XY tarXy) {
            return Walk(tarXy.X, tarXy.Y);
        }

        protected void LevelUp() {
            //void LevelUp(int CALL_LEVEL_UP, int JsOff1);
            DllCall(FuncId.VmMyLevelup, Data.CALL_LEVEL_UP, Data.JS_OFF_1);
        }

        protected void Drop(int id) {
            //void Drop(int PET, int CALL_OFF_DROP_1, int CALL_OFF_DROP_2, int ID, int CALL_DROP);
            DllCall(FuncId.VmMyDrop, Data.PET, Data.CALL_OFF_DROP_1, Data.CALL_OFF_DROP_2, id, Data.CALL_DROP);
        }

        protected void CailiaoJg(int type) {
            //void CailiaoJiaGong(int ID, int CallAddr);
            DllCall(FuncId.VmMyCailiaojiagong, type, Data.CALL_CAILIAOJIAGONG);
        }

        protected void PetKillCall(int tarId = -1) {
            Skill_Common(-1, tarId);
        }
        #endregion
    }
}

